﻿using System.Diagnostics;

namespace FluentParser.Expressions.Rules.Decoration
{
    /// <summary>
    /// Decorates an expression by casting all it's results into TResult.
    /// </summary>
    /// <typeparam name="TSource">Type of the source result</typeparam>
    /// <typeparam name="TResult">Type of the new result</typeparam>
    /// <example><code>
    /// var sourceExpr = ...;
    /// var castExpr = sourceExpr.Cast&lt;string&gt;();
    /// 
    /// sourceResult = sourceExpr.Parse(...) --> object
    /// castedResult = castExpr.Parse(...)   --> string
    /// </code></example>
    [DebuggerDisplay("[CastToExpressionRule Source={Source.GetType().Name}]")]
    public class CastToExpressionRule<TSource, TResult> : Expr<TResult>
    {
        public BaseExpr<TSource> Source { get; private set; }

        public CastToExpressionRule(BaseExpr<TSource> source)
        {
            Source = source;
            TypeOperation = OperationType.Structural;
        }

        public override ParsingResult<TResult> Parse(GrammarContext context, int index)
        {
            ParsingResult<TSource> result = Source.Parse(context, index);
            if (result == null)
                return null;

            return new ParsingResult<TResult>(result.Index, result.Length, (TResult)(object)result.Value);
        }

        public override void ParseNode(GrammarContext context, ParsingNodeResult node)
        {
            ParsingNodeResult childNode = node.AddChild(Source, context);
            node.Value = childNode.Value;
            node.IsSuccess = childNode.IsSuccess;
        }
    }
}